package com.fintech.pangu.security.authentication.token.impl;

import com.fintech.pangu.security.authentication.token.AuthenticationToken;
import com.fintech.pangu.security.authentication.token.AuthenticationTokenServices;
import com.fintech.pangu.security.authentication.token.AuthenticationTokenStore;
import lombok.Setter;
import org.springframework.security.core.Authentication;

import java.util.UUID;

/**
 * 认证令牌服务的默认实现，模板类
 */
@Setter
public class DefaultAuthenticationTokenServices implements AuthenticationTokenServices {

    /**
     * token存储
     */
    private AuthenticationTokenStore tokenStore;

    /**
     * 获取TokenStore实现，默认是InMemoryAuthenticationTokenStore
     * @return
     */
    private AuthenticationTokenStore getTokenStore() {
        if(tokenStore == null){
            synchronized (this){
                if(tokenStore == null){
                    tokenStore = new InMemoryAuthenticationTokenStore();
                }
            }
        }

        return tokenStore;
    }


    /**
     * 创建认证令牌
     * @param authentication
     * @return
     */
    @Override
    public AuthenticationToken createAuthenticationToken(Authentication authentication) {
        AuthenticationToken existingToken = getTokenStore().getAuthenticationToken(authentication);

        if(existingToken != null){
            return existingToken;
        }

        // 创建新AuthenticationToken
        AuthenticationToken token = createAuthenticationTokenInner(authentication);
        // 持久化AuthenticationToken
        getTokenStore().storeAuthenticationToken(token, authentication);

        return token;
    }

    /**
     * 内部真正创建认证令牌逻辑，默认UUID
     * 子类可覆盖
     * @param authentication
     * @return
     */
    protected AuthenticationToken createAuthenticationTokenInner(Authentication authentication) {
        AuthenticationToken token = new DefaultAuthenticationToken();
        token.setValue(UUID.randomUUID().toString()); // UUID

        return token;
    }


    /**
     * 获取认证令牌
     * @param authentication
     * @return
     */
    @Override
    public AuthenticationToken getAuthenticationToken(Authentication authentication) {
        return tokenStore.getAuthenticationToken(authentication);
    }


}
